import java.util.LinkedList;
import java.util.Queue;

public class BinaryTree {

    public static class TreeNode{
        TreeNode left;
        TreeNode right;
        char value;

        public TreeNode(char value) {
            this.value = value;
        }
    }

    private TreeNode root;

    @Override
    public String toString() {
        return "BinaryTree{" +
                "root=" + root +
                '}';
    }

    public TreeNode createTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        root=A;
        A.left=B;
        A.right=C;
        B.left=D;
        B.right=E;
        C.left=F;
        C.right=G;
        D.left=H;
        return root;
    }

    public TreeNode createTree2(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        TreeNode L = new TreeNode('L');
        root=A;
        A.left=B;
        A.right=C;
        B.left=D;
        B.right=E;
        C.left=F;
        C.right=G;
        D.left=H;
        E.right=L;
        return root;
    }

    //前序遍历
    public void preOrder(TreeNode root){
        System.out.print(root.value);
        if(root.left!=null) preOrder(root.left);
        if(root.right!=null) preOrder(root.right);
    }

    //后序遍历
    public void postOrder(TreeNode root){
        if (root.left!=null) postOrder(root.left);
        if (root.right!=null) postOrder(root.right);
        System.out.print(root.value);
    }

    //中序遍历
    public void inOrder(TreeNode root){
        if (root.left!=null) inOrder(root.left);
        System.out.print(root.value);
        if (root.right!=null) inOrder(root.right);
    }

    //层序遍历
    public void levelOrder(TreeNode root){
        if (root==null) {
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int sz = queue.size();
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                System.out.print(node.value);
                if (node.left!=null){
                    queue.offer(node.left);
                }
                if (node.right!=null){
                    queue.offer(node.right);
                }
            }
        }
    }

    //判断二叉树是不是完全二叉树
    public boolean isCompleteTree(TreeNode root){
        if (root==null){
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node!=null){
                queue.offer(node.left);
                queue.offer(node.right);
            }else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            TreeNode node = queue.peek();
            if (node!=null){
                return false;
            }
            queue.poll();
        }
        return  true;
    }

    //获取树中节点的个数
    public int size(TreeNode root) {
        if (root==null){
            return 0;
        }
        return size(root.left)+size(root.right)+1;
    }

    //获取叶子节点个数
    //子问题思路
    public int getLeafNodeCount1(TreeNode root){
        int size = 0;
        if(root==null){
            return 0;
        }
        if(root.left==null&&root.right==null){
            size++;
        }
        size+=getLeafNodeCount1(root.left);
        size+=getLeafNodeCount1(root.right);
        return size;
    }

    public static int leafSize=0;
    public void getLeafNodeCount2(TreeNode root){
        if (root==null){
            return;
        }
        if(root.left==null&&root.right==null){
            leafSize++;
        }
        getLeafNodeCount2(root.left);
        getLeafNodeCount2(root.right);
    }

    //获取叶子节点个数
    public int getLeafNodeCount3(TreeNode root){
        if(root==null){
            return 0;
        }
        if(root.left==null&&root.right==null){
            return 1;
        }
        return getLeafNodeCount3(root.left)+getLeafNodeCount3(root.right);
    }

    //递归实现获取第K层节点的个数
    public int getKLevelNodeCount(TreeNode root,int k){
        if (root==null){
            return 0;
        }
        if (k==1){
            return 1;
        }
        return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
    }
    //获取第K层节点的个数
    public int getKLevelNodeCount1(TreeNode root,int k){
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int height=1;//记录层数
        int sz=1;
        while (!queue.isEmpty()){
            sz=queue.size();
            if (height==k){
                sz=queue.size();
                break;
            }
            for (int i = 0; i < sz; i++) {
                TreeNode node = queue.poll();
                if(node.left!=null){
                    queue.offer(node.left);
                }
                if(node.right!=null){
                    queue.offer(node.right);
                }
            }
            height++;
        }
        return sz;
    }

    //获取二叉树的高度
    public int getHeight(TreeNode root){
        if (root==null){
            return 0;
        }
        return Math.max(getHeight(root.left),getHeight(root.right))+1;
    }

    //判断是否存在value元素
    public boolean find(TreeNode root,char value){
        if (root==null){
            return false;
        }
        if(root.value==value){
            return true;
        }
        return find(root.left,value) || find(root.right,value);
    }

    public TreeNode findValue(TreeNode root,char value){
        if (root==null){
            return null;
        }
        if (root.value==value){
            return root;
        }
        //去左子树中寻找，并且记录，如果不为null，则表示找到，直接返回
        TreeNode leftTreeNode = findValue(root.left,value);
        if (leftTreeNode!=null){
            return leftTreeNode;
        }
        //去右子树中寻找，并且记录，如果不为null，则表示找到，直接返回
        TreeNode rightTreeNode = findValue(root.left,value);
        if (leftTreeNode!=null){
            return leftTreeNode;
        }
        //此时左右子树都没找到，返回null
        return null;
    }

}
